/* ------------------------------------------------------------------------*
 *
 * ------------------------------------------------------------------------*/
#include "gd25q_cmd.h"
#include "mytype.h"

void gd25qWait(uint8_t Cnt)
{
    while(Cnt --){};
}

/*****************************************************************************//*!
* @brief   read status.
*               The Status Register may be read at any time, 
*               even while a Program, Erase or Write Status Register cycle is in progress. 
* @param   none
*
* @return  statues
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
uint32_t gd25qCmdStRead(void)
{
    UINT32_VAL FlashSt;
    
    GD25Cs(0); 
    FlashSt.byte.MB = 0;
    dgSpiRw( GD25CMD_Read_StReg1);
    FlashSt.byte.LB = dgSpiRw( 0xFF);
    GD25Cs(1); 
    gd25qWait(2);
    GD25Cs(0); 
    dgSpiRw( GD25CMD_Read_StReg2);
    FlashSt.byte.HB = dgSpiRw( 0xFF);
    GD25Cs(1); 
    gd25qWait(2);
    GD25Cs(0); 
    dgSpiRw( GD25CMD_Read_StReg3);
    FlashSt.byte.UB = dgSpiRw( 0xFF);
    GD25Cs(1); 
    
    return FlashSt.Val;
}

/*****************************************************************************//*!
* @brief   read busy statues.
*               The Status Register may be read at any time, 
*               even while a Program, Erase or Write Status Register cycle is in progress. 
* @param   none
*
* @return  busy or not
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
uint8_t  gd25qBusy(void)
{
    uint8_t FlashSt;
    
    GD25Cs(0); 
    dgSpiRw( GD25CMD_Read_StReg1);
    FlashSt = dgSpiRw( 0xFF);
    GD25Cs(1); 
    
    return ((uint8_t)(FlashSt & GD25Q_ST_BUSY_MASK));
}

/*****************************************************************************//*!
* @brief   write enable.
*               
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qCmdWriteEn(void)
{
    GD25Cs(0); 

    dgSpiRw( GD25CMD_Write_Enable);
   
    GD25Cs(1); 
}

/*****************************************************************************//*!
* @brief   write disable.
*               
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qCmdWriteDis(void)
{
    GD25Cs(0); 

    dgSpiRw( GD25CMD_Write_Disable);
   
    GD25Cs(1); 
}

/*****************************************************************************//*!
* @brief   Erase aector.       4k
*               
* @param   addr:      data address in chip
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qSectorErase(uint32_t addr)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
        
    gd25qCmdWriteEn();
        
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Sector_Erase);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB); 
    GD25Cs(1);
}

/*****************************************************************************//*!
* @brief   Erase block.      32k
*               
* @param   addr:      data address in chip
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void gd25qBlockErase(uint32_t addr)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
        
    gd25qCmdWriteEn();
        
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Block_Erase_32K);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB); 
    GD25Cs(1);
}

/*****************************************************************************//*!
* @brief   Erase chip.
*               
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void gd25qChipErase(void )
{
     while(gd25qBusy()){}
        
    gd25qCmdWriteEn();
        
    GD25Cs(0);  
    dgSpiRw( GD25CMD_Chip_Erase);
    GD25Cs(1);   
}

/*****************************************************************************//*!
* @brief   read data.
*               
* @param   addr          address in chip
*          len           length will be read
*          des           destination
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qRead(uint32_t addr,uint32_t Len,uint8_t *Des)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
    //
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Read_Data);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB);
    while(Len--)
    {
        *Des++ = dgSpiRw( 0xFF );
    } 
    
    GD25Cs(1);
}

/*****************************************************************************//*!
* @brief   write data ,must be in same page.
*               
* @param   addr          address in chip
*          len           length will be read
*          des           source
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qWrite(uint32_t addr,uint32_t Len,uint8_t *Src)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
        
    gd25qCmdWriteEn();
        
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Page_Program);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB);
    while(Len--)
    {
        dgSpiRw( *Src++ );
    }  
    GD25Cs(1);
}

/*****************************************************************************//*!
* @brief   read data.
*               
* @param   addr          address in chip
*          len           length will be read
*          des           destination
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qDmaRead(uint32_t addr,uint32_t Len,uint8_t *Des)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
    //
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Read_Data);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB);

    gdSpiDmaRw(GD25Q_READ,  Len, Des);
    GD25Cs(1);
}

/*****************************************************************************//*!
* @brief   write data ,must be in same page.
*               
* @param   addr          address in chip
*          len           length will be read
*          des           source
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/ 
void gd25qDmaWrite(uint32_t addr,uint32_t Len,uint8_t *Src)
{
    UINT32_VAL Par;
    
    //waiting for idle
    while(gd25qBusy()){}
        
    gd25qCmdWriteEn();
        
    GD25Cs(0);
    Par.Val = addr;   
    dgSpiRw( GD25CMD_Page_Program);
    dgSpiRw( Par.byte.UB);
    dgSpiRw( Par.byte.HB);
    dgSpiRw( Par.byte.LB);
	
    gdSpiDmaRw(GD25Q_WRITE,  Len, Src);
    
    GD25Cs(1);
}
